﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using QASPRibbon.Commands;
using QASPRibbon.Helpers;
using Schema = QASPRibbon.RibbonSchema;

namespace QASPRibbon.Controls
{
    /// <summary>
    /// Represents a ComboBox control in the SharePoint Server Ribbon.
    /// </summary>
    public class RibbonComboBox : RibbonVisualControl, IRibbonMenu
    {
        #region Properties

        ///<summary>
        /// A value that indicates whether input is restricted so that only items on the menu are submitted. 
        /// The default is False.
        ///</summary>
        public bool AllowFreeForm { get; set; }

        /// <summary>
        /// An alternative text that is used for the drop-down arrow button.
        /// </summary>
        public string AltArrow
        {
            get { return _altArrow.Localized(); }
            set { _altArrow = value; }
        }

        /// <summary>
        /// An alternative text that is used for the combo box.
        /// </summary>
        public string Alt
        {
            get { return _alt.Localized(); }
            set { _alt = value; }
        }

        ///<summary>
        /// A value that indicates whether autocomplete suggestions is turned on (True) or off (False). 
        /// The default is False (off).
        ///</summary>
        public bool AutoComplete
        {
            get { return _autoComplete; }
            set { _autoComplete = value; }
        }

        /// <summary>
        /// A value that represents a delay in milliseconds before AutoComplete fills the text box with a best-guess match. 
        /// The default is 100.
        /// </summary>
        public uint AutoCompleteDelay
        {
            get { return _autoCompleteDelay; }
            set { _autoCompleteDelay = value; }
        }

        /// <summary>
        /// A value that indicates whether constructed versions of a dynamic menu is stored to use in next time. 
        /// The default is False.
        /// </summary>
        public bool CacheMenuVersions { get; set; }

        /// <summary>
        /// A value that indicates whether Input Method Editor (IME) is activated.
        /// The default is False.
        /// </summary>
        public bool ImeEnabled { get; set; }

        /// <summary>
        /// A value that indicates whether a menu will be created dynamically (True) or not (False).
        /// The default is False.
        /// </summary>
        public bool PopulateDynamically { get; set; }

        /// <summary>
        /// A value that indicates whether a dynamic menu will be populated only the first time that it is accessed. 
        /// The default is False.
        /// </summary>
        public bool PopulateOnlyOnce { get; set; }

        /// <summary>
        /// The width in pixels of the text box that is part of this combo box.
        /// The default is 100.
        /// </summary>
        public uint Width
        {
            get { return _width; }
            set { _width = value; }
        }

        ///<summary>
        /// Sections used in root level of this combo box.
        ///</summary>
        [Obsolete("Use property Controls instead Sections")]
        public IEnumerable<RibbonMenuSection> Sections { get { return Controls; } set { Controls = value; } }

        /// <summary>
        /// Child controls.
        /// </summary>
        public IEnumerable<RibbonMenuSection> Controls { get; set; }

        /// <summary>
        /// Client-side script that executes when a ComboBox is activated.
        /// </summary>
        public string OnClientActivate
        {
            get { return _onClientActivate; }
            set { _onClientActivate = value; }
        }

        /// <summary>
        /// Client-side script that executes when menu is closed.
        /// </summary>
        public string OnClientMenuClose
        {
            get { return _onClientMenuClose; }
            set { _onClientMenuClose = value; }
        }

        /// <summary>
        /// Client-side script that executes when menu is populated.
        /// </summary>
        public string OnClientMenuOpen
        {
            get { return _onClientMenuOpen; }
            set { _onClientMenuOpen = value; }
        }

        /// <summary>
        /// Client-side script that executes before checking ComboBox is enabled or not.
        /// </summary>
        public string OnClientStateCheck
        {
            get { return _onClientStateCheck; }
            set { _onClientStateCheck = value; }
        }

        internal override string XmlTag
        {
            get { return Schema.ComboBox; }
        }

        #endregion

        #region Internal

        internal override IEnumerable<RibbonCommand> ClientCommands
        {
            get
            {
                var res = new List<RibbonCommand>
                              {
                                  new RibbonCommand(FullId, Schema.CheckState,
                                                    string.Format("{0}; {1}; return {2}",
                                                                  OnClientActivate ?? string.Empty, OnClientStateCheck,
                                                                  Enabled ? "true" : "false")),
                                    new RibbonCommand(FullId, Schema.Command, string.Empty)
                              };

                if (!string.IsNullOrEmpty(OnClientMenuOpen))
                    res.Add(new RibbonCommand(FullId, Schema.CommandMenuOpen, OnClientMenuOpen));
                if (!string.IsNullOrEmpty(OnClientMenuClose))
                    res.Add(new RibbonCommand(FullId, Schema.CommandMenuClose, OnClientMenuClose));
                return res;
            }
        }

        internal override XElement AsXElement()
        {
            var element = base.AsXElement();
            if (Width > 0)
                element.Add(new XAttribute(Schema.Width, Width + "px"));
            element.Add(new XAttribute(Schema.AutoComplete, AutoComplete ? "true" : "false"));
            element.Add(new XAttribute(Schema.AutoCompleteDelay, AutoCompleteDelay));
            element.Add(new XAttribute(Schema.AllowFreeForm, AllowFreeForm ? "true" : "false"));
            element.Add(new XAttribute(Schema.TemplateAlias, TemplateAlias));
            element.Add(new XAttribute(Schema.CacheMenuVersions, CacheMenuVersions ? "true" : "false"));
            element.Add(new XAttribute(Schema.PopulateDynamically, PopulateDynamically ? "true" : "false"));
            element.Add(new XAttribute(Schema.PopulateOnlyOnce, PopulateOnlyOnce ? "true" : "false"));

            element.Add(new XAttribute(Schema.QueryCommand, FullId + Schema.QueryCommand));
            element.Add(new XAttribute(Schema.Command, FullId + Schema.Command));
            element.Add(new XAttribute(Schema.CommandMenuOpen, FullId + Schema.CommandMenuOpen));
            element.Add(new XAttribute(Schema.CommandMenuClose, FullId + Schema.CommandMenuClose));

            var menuElement = new XElement(Schema.Menu, new XAttribute(Schema.Id, FullId + ".Menu"));
            var sectionIndex = 0;
            
            foreach (var section in Controls)
            {
                sectionIndex++;
                section.Sequence = sectionIndex;
                section.NameSpace = FullId + ".Menu";
                menuElement.Add(section.AsXElement());
            }
            foreach (var section in Controls)
            {
                section.SetMenuFullId(this);
            }
            element.Add(new XAttribute(Schema.InitialItem, Controls.First().Controls.First().FullId));
            element.Add(menuElement);
            element.Add();

            return element;
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Creates and initializes a new instance of the RibbonComboBox.
        /// </summary>
        public RibbonComboBox() { }

        /// <summary>
        /// Creates and initializes a new instance of the RibbonComboBox.
        /// </summary>
        /// <param name="id">Control' identifier</param>
        public RibbonComboBox(string id) : base(id) { }

        /// <summary>
        /// Creates and initializes a new instance of the RibbonComboBox.
        /// </summary>
        /// <param name="id">Control' identifier</param>
        /// <param name="title">Control' title</param>
        public RibbonComboBox(string id, string title) : base(id, title) { }

        #endregion

        #region Private fields

        private string _alt = string.Empty;
        private string _altArrow = string.Empty;
        private bool _autoComplete = true;
        private uint _autoCompleteDelay = 100;
        private uint _width = 100;
        private string _onClientActivate = string.Empty;
        private string _onClientMenuClose = string.Empty;
        private string _onClientStateCheck = string.Empty;
        private string _onClientMenuOpen = string.Empty;

        #endregion

        #region PostBack Action

        /// <summary>
        /// Occurs when the Button control is clicked.
        /// </summary>
        public event RibbonComboBoxEventHandler OnAction;

        internal void DoOnAction(RibbonComboBoxEventArgs e)
        {
            var handler = OnAction;
            if (handler != null) handler(this, e);
        }

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    public delegate void RibbonComboBoxEventHandler(object sender, RibbonComboBoxEventArgs e);

    /// <summary>
    /// Arguments of server ation rised by RibbonButton
    /// </summary>
    public class RibbonComboBoxEventArgs : EventArgs
    {
        /// <summary>
        /// 
        /// </summary>
        public RibbonComboBox Instance;
        /// <summary>
        /// 
        /// </summary>
        public string SelectedValue;

        internal RibbonComboBoxEventArgs(RibbonComboBox comboBox, string selectedValue)
        {
            Instance = comboBox;
            SelectedValue = selectedValue;
        }
    }
}
